"""
AIQuant Web数据服务层
统一的数据访问接口，集成API客户端、缓存管理和降级机制
"""

import logging
from typing import Any, Dict, List, Optional

import pandas as pd

from aiquant.web.utils.api_client import get_api_client, APIError
from aiquant.web.utils.cache_manager import cached_api_call, get_cache_manager
from aiquant.web.utils.fallback_data import with_fallback, get_fallback_provider

logger = logging.getLogger(__name__)


class DataService:
    """
    数据服务类
    
    提供统一的数据访问接口，包括：
    - 系统状态和健康检查
    - 数据源管理
    - 市场数据获取
    - 交易相关数据
    - 持仓组合数据
    - 策略管理数据
    - 风险管理数据
    """
    
    def __init__(self):
        """初始化数据服务"""
        self.api_client = get_api_client()
        self.cache_manager = get_cache_manager()
        self.fallback_provider = get_fallback_provider()
    
    # ==================== 系统相关服务 ====================
    
    @with_fallback('get_system_status', show_warning=True)
    @cached_api_call(ttl=30, key_prefix="system")
    def get_system_status(self) -> Dict[str, Any]:
        """
        获取系统状态
        
        Returns:
            系统状态信息
        """
        try:
            from aiquant.web.utils.api_client import api_get
            return api_get('/api/system/status')
        except APIError as e:
            logger.error(f"获取系统状态失败: {e.message}")
            raise
    
    @with_fallback('get_system_health', show_warning=True)
    @cached_api_call(ttl=60, key_prefix="system")
    def get_system_health(self) -> Dict[str, Any]:
        """
        获取系统健康检查
        
        Returns:
            系统健康信息
        """
        try:
            from aiquant.web.utils.api_client import api_get
            return api_get('/api/system/health')
        except APIError as e:
            logger.error(f"获取系统健康状态失败: {e.message}")
            raise
    
    # ==================== 数据管理服务 ====================
    
    @with_fallback('get_data_sources', show_warning=True)
    @cached_api_call(ttl=300, key_prefix="data")
    def get_data_sources(self) -> List[Dict[str, Any]]:
        """
        获取数据源列表
        
        Returns:
            数据源列表
        """
        try:
            from aiquant.web.utils.api_client import api_get
            response = api_get('/api/data/sources')
            return response.get('data', [])
        except APIError as e:
            logger.error(f"获取数据源列表失败: {e.message}")
            raise
    
    @with_fallback('get_data_quality_metrics', show_warning=True)
    @cached_api_call(ttl=180, key_prefix="data")
    def get_data_quality_metrics(self) -> Dict[str, Any]:
        """
        获取数据质量指标
        
        Returns:
            数据质量指标
        """
        try:
            from aiquant.web.utils.api_client import api_get
            return api_get('/api/data/quality/metrics')
        except APIError as e:
            logger.error(f"获取数据质量指标失败: {e.message}")
            raise
    
    def refresh_data_source(self, source_id: str) -> Dict[str, Any]:
        """
        刷新数据源
        
        Args:
            source_id: 数据源ID
            
        Returns:
            刷新结果
        """
        try:
            from aiquant.web.utils.api_client import api_post
            result = api_post(f'/api/data/sources/{source_id}/refresh')
            
            # 清除相关缓存
            self.cache_manager.delete(f"data_get_data_sources_{self.cache_manager._generate_key()}")
            
            return result
        except APIError as e:
            logger.error(f"刷新数据源失败: {e.message}")
            return {'success': False, 'message': f'刷新失败: {e.message}'}
    
    def test_data_connection(self, config: Dict[str, Any]) -> Dict[str, Any]:
        """
        测试数据连接
        
        Args:
            config: 连接配置
            
        Returns:
            测试结果
        """
        try:
            from aiquant.web.utils.api_client import api_post
            return api_post('/api/data/test-connection', json_data=config)
        except APIError as e:
            logger.error(f"测试数据连接失败: {e.message}")
            return {'success': False, 'message': f'连接测试失败: {e.message}'}
    
    # ==================== 市场数据服务 ====================
    
    @with_fallback('get_market_quotes', show_warning=True)
    @cached_api_call(ttl=5, key_prefix="market")
    def get_market_quotes(self) -> Dict[str, Any]:
        """
        获取市场行情
        
        Returns:
            市场行情数据
        """
        try:
            from aiquant.web.utils.api_client import api_get
            return api_get('/api/market/quotes')
        except APIError as e:
            logger.error(f"获取市场行情失败: {e.message}")
            raise
    
    @with_fallback('get_market_kline', show_warning=True)
    @cached_api_call(ttl=60, key_prefix="market")
    def get_market_kline(self, symbol: str, period: str) -> Dict[str, Any]:
        """
        获取K线数据
        
        Args:
            symbol: 股票代码
            period: 时间周期
            
        Returns:
            K线数据
        """
        try:
            from aiquant.web.utils.api_client import api_get
            params = {'symbol': symbol, 'period': period}
            return api_get('/api/market/kline', params=params)
        except APIError as e:
            logger.error(f"获取K线数据失败: {e.message}")
            raise
    
    @with_fallback('get_realtime_quotes', show_warning=True)
    @cached_api_call(ttl=5, key_prefix="market")
    def get_realtime_quotes(self, symbols: Optional[List[str]] = None) -> pd.DataFrame:
        """
        获取实时行情
        
        Args:
            symbols: 股票代码列表
            
        Returns:
            实时行情DataFrame
        """
        try:
            from aiquant.web.utils.api_client import api_get
            params = {'symbols': ','.join(symbols)} if symbols else {}
            response = api_get('/api/market/quotes/realtime', params=params)
            
            if 'data' in response:
                return pd.DataFrame(response['data'])
            else:
                return pd.DataFrame()
        except APIError as e:
            logger.error(f"获取实时行情失败: {e.message}")
            raise
    
    @with_fallback('get_kline_data', show_warning=True)
    @cached_api_call(ttl=60, key_prefix="market")
    def get_kline_data(self, symbol: str, period: str = '1d', limit: int = 100) -> pd.DataFrame:
        """
        获取K线数据
        
        Args:
            symbol: 股票代码
            period: 时间周期
            limit: 数据条数
            
        Returns:
            K线数据DataFrame
        """
        try:
            from aiquant.web.utils.api_client import api_get
            params = {'symbol': symbol, 'period': period, 'limit': limit}
            response = api_get('/api/market/kline', params=params)
            
            if 'data' in response:
                return pd.DataFrame(response['data'])
            else:
                return pd.DataFrame()
        except APIError as e:
            logger.error(f"获取K线数据失败: {e.message}")
            raise
    
    @cached_api_call(ttl=10, key_prefix="market")
    def get_market_depth(self, symbol: str) -> Dict[str, Any]:
        """
        获取市场深度
        
        Args:
            symbol: 股票代码
            
        Returns:
            市场深度数据
        """
        try:
            from aiquant.web.utils.api_client import api_get
            params = {'symbol': symbol}
            return api_get('/api/market/depth', params=params)
        except APIError as e:
            logger.error(f"获取市场深度失败: {e.message}")
            return {'bids': [], 'asks': [], 'symbol': symbol}
    
    # ==================== 交易相关服务 ====================
    
    @with_fallback('get_trading_orders', show_warning=True)
    @cached_api_call(ttl=10, key_prefix="trading")
    def get_trading_orders(self) -> Dict[str, Any]:
        """
        获取交易订单
        
        Returns:
            交易订单数据
        """
        try:
            from aiquant.web.utils.api_client import api_get
            return api_get('/api/trading/orders')
        except APIError as e:
            logger.error(f"获取交易订单失败: {e.message}")
            raise
    
    @with_fallback('get_trading_positions', show_warning=True)
    @cached_api_call(ttl=30, key_prefix="trading")
    def get_trading_positions(self) -> Dict[str, Any]:
        """
        获取交易持仓
        
        Returns:
            交易持仓数据
        """
        try:
            from aiquant.web.utils.api_client import api_get
            return api_get('/api/trading/positions')
        except APIError as e:
            logger.error(f"获取交易持仓失败: {e.message}")
            raise
    
    @with_fallback('get_active_orders', show_warning=True)
    @cached_api_call(ttl=10, key_prefix="trading")
    def get_active_orders(self) -> List[Dict[str, Any]]:
        """
        获取活跃订单
        
        Returns:
            活跃订单列表
        """
        try:
            from aiquant.web.utils.api_client import api_get
            response = api_get('/api/trading/orders/active')
            return response.get('data', [])
        except APIError as e:
            logger.error(f"获取活跃订单失败: {e.message}")
            raise
    
    @with_fallback('get_trade_history', show_warning=True)
    @cached_api_call(ttl=60, key_prefix="trading")
    def get_trade_history(self, limit: int = 50) -> List[Dict[str, Any]]:
        """
        获取交易历史
        
        Args:
            limit: 记录数量限制
            
        Returns:
            交易历史列表
        """
        try:
            from aiquant.web.utils.api_client import api_get
            params = {'limit': limit}
            response = api_get('/api/trading/trades/history', params=params)
            return response.get('data', [])
        except APIError as e:
            logger.error(f"获取交易历史失败: {e.message}")
            raise
    
    @cached_api_call(ttl=30, key_prefix="trading")
    def get_execution_stats(self) -> Dict[str, Any]:
        """
        获取执行统计
        
        Returns:
            执行统计数据
        """
        try:
            from aiquant.web.utils.api_client import api_get
            return api_get('/api/trading/execution/stats')
        except APIError as e:
            logger.error(f"获取执行统计失败: {e.message}")
            return {
                'total_trades': 0,
                'success_rate': 0.0,
                'avg_execution_time': 0.0,
                'slippage': 0.0
            }
    
    def submit_order(self, order_data: Dict[str, Any]) -> Dict[str, Any]:
        """
        提交订单
        
        Args:
            order_data: 订单数据
            
        Returns:
            提交结果
        """
        try:
            from aiquant.web.utils.api_client import api_post
            result = api_post('/api/trading/orders', json_data=order_data)
            
            # 清除相关缓存
            self.cache_manager.delete(f"trading_get_active_orders_{self.cache_manager._generate_key()}")
            
            return result
        except APIError as e:
            logger.error(f"提交订单失败: {e.message}")
            return {'success': False, 'message': f'订单提交失败: {e.message}'}
    
    def create_order(self, order_data: Dict[str, Any]) -> Dict[str, Any]:
        """
        创建交易订单
        
        Args:
            order_data: 订单数据
            
        Returns:
            创建结果
        """
        return self.submit_order(order_data)
    
    # ==================== 持仓组合服务 ====================
    
    @with_fallback('get_portfolio_positions', show_warning=True)
    @cached_api_call(ttl=30, key_prefix="portfolio")
    def get_portfolio_positions(self) -> List[Dict[str, Any]]:
        """
        获取持仓信息
        
        Returns:
            持仓信息列表
        """
        try:
            from aiquant.web.utils.api_client import api_get
            response = api_get('/api/portfolio/positions')
            return response.get('data', [])
        except APIError as e:
            logger.error(f"获取持仓信息失败: {e.message}")
            raise
    
    @with_fallback('get_portfolio_performance', show_warning=True)
    @cached_api_call(ttl=60, key_prefix="portfolio")
    def get_portfolio_performance(self) -> Dict[str, Any]:
        """
        获取组合绩效
        
        Returns:
            组合绩效数据
        """
        try:
            from aiquant.web.utils.api_client import api_get
            return api_get('/api/portfolio/performance')
        except APIError as e:
            logger.error(f"获取组合绩效失败: {e.message}")
            raise
    
    @cached_api_call(ttl=120, key_prefix="portfolio")
    def get_portfolio_attribution(self) -> Dict[str, Any]:
        """
        获取绩效归因
        
        Returns:
            绩效归因数据
        """
        try:
            from aiquant.web.utils.api_client import api_get
            return api_get('/api/portfolio/attribution')
        except APIError as e:
            logger.error(f"获取绩效归因失败: {e.message}")
            return {
                'sector_attribution': {},
                'stock_attribution': {},
                'factor_attribution': {}
            }
    
    def get_portfolio_summary(self) -> Dict[str, Any]:
        """
        获取持仓摘要
        
        Returns:
            持仓摘要数据
        """
        try:
            from aiquant.web.utils.api_client import api_get
            return api_get('/api/portfolio/summary')
        except APIError as e:
            logger.error(f"获取持仓摘要失败: {e.message}")
            return {
                'total_value': 0,
                'total_cost': 0,
                'total_pnl': 0,
                'positions_count': 0
            }
    
    # ==================== 策略管理服务 ====================
    
    @with_fallback('get_strategies', show_warning=True)
    @cached_api_call(ttl=120, key_prefix="strategy")
    def get_strategies(self) -> List[Dict[str, Any]]:
        """
        获取策略列表
        
        Returns:
            策略列表
        """
        try:
            from aiquant.web.utils.api_client import api_get
            response = api_get('/api/strategies')
            return response.get('data', [])
        except APIError as e:
            logger.error(f"获取策略列表失败: {e.message}")
            raise
    
    @with_fallback('get_strategy_performance', show_warning=True)
    @cached_api_call(ttl=300, key_prefix="strategy")
    def get_strategy_performance(self, strategy_id: str) -> Dict[str, Any]:
        """
        获取策略绩效
        
        Args:
            strategy_id: 策略ID
            
        Returns:
            策略绩效数据
        """
        try:
            from aiquant.web.utils.api_client import api_get
            return api_get(f'/api/strategies/{strategy_id}/performance')
        except APIError as e:
            logger.error(f"获取策略绩效失败: {e.message}")
            raise
    
    def run_backtest(self, strategy_id: str, config: Dict[str, Any]) -> Dict[str, Any]:
        """
        运行回测
        
        Args:
            strategy_id: 策略ID
            config: 回测配置
            
        Returns:
            回测结果
        """
        try:
            from aiquant.web.utils.api_client import api_post
            return api_post(f'/api/strategies/{strategy_id}/backtest', json_data=config)
        except APIError as e:
            logger.error(f"运行回测失败: {e.message}")
            return {'success': False, 'message': f'回测失败: {e.message}'}
    
    def deploy_strategy(self, strategy_id: str, config: Dict[str, Any]) -> Dict[str, Any]:
        """
        部署策略
        
        Args:
            strategy_id: 策略ID
            config: 部署配置
            
        Returns:
            部署结果
        """
        try:
            from aiquant.web.utils.api_client import api_post
            result = api_post(f'/api/strategies/{strategy_id}/deploy', json_data=config)
            
            # 清除相关缓存
            self.cache_manager.delete(f"strategy_get_strategies_{self.cache_manager._generate_key()}")
            
            return result
        except APIError as e:
            logger.error(f"部署策略失败: {e.message}")
            return {'success': False, 'message': f'策略部署失败: {e.message}'}
    
    def create_strategy(self, strategy_data: Dict[str, Any]) -> Dict[str, Any]:
        """
        创建新策略
        
        Args:
            strategy_data: 策略数据
            
        Returns:
            创建结果
        """
        try:
            from aiquant.web.utils.api_client import api_post
            result = api_post('/api/strategies', json_data=strategy_data)
            
            # 清除相关缓存
            self.cache_manager.delete(f"strategy_get_strategies_{self.cache_manager._generate_key()}")
            
            return result
        except APIError as e:
            logger.error(f"创建策略失败: {e.message}")
            return {'success': False, 'message': f'策略创建失败: {e.message}'}
    
    # ==================== 风险管理服务 ====================
    
    @with_fallback('get_risk_metrics', show_warning=True)
    @cached_api_call(ttl=60, key_prefix="risk")
    def get_risk_metrics(self) -> Dict[str, Any]:
        """
        获取风险指标
        
        Returns:
            风险指标数据
        """
        try:
            from aiquant.web.utils.api_client import api_get
            return api_get('/api/risk/metrics')
        except APIError as e:
            logger.error(f"获取风险指标失败: {e.message}")
            raise
    
    @with_fallback('get_risk_alerts', show_warning=True)
    @cached_api_call(ttl=30, key_prefix="risk")
    def get_risk_alerts(self) -> List[Dict[str, Any]]:
        """
        获取风险预警
        
        Returns:
            风险预警列表
        """
        try:
            from aiquant.web.utils.api_client import api_get
            response = api_get('/api/risk/alerts')
            return response.get('data', [])
        except APIError as e:
            logger.error(f"获取风险预警失败: {e.message}")
            raise
    
    def run_stress_test(self, config: Dict[str, Any]) -> Dict[str, Any]:
        """
        运行压力测试
        
        Args:
            config: 压力测试配置
            
        Returns:
            压力测试结果
        """
        try:
            from aiquant.web.utils.api_client import api_post
            return api_post('/api/risk/stress-test', json_data=config)
        except APIError as e:
            logger.error(f"运行压力测试失败: {e.message}")
            return {'success': False, 'message': f'压力测试失败: {e.message}'}
    
    # ==================== 工具方法 ====================
    
    def clear_cache(self, pattern: Optional[str] = None) -> int:
        """
        清理缓存
        
        Args:
            pattern: 缓存键模式
            
        Returns:
            清理的缓存项数量
        """
        if pattern:
            # TODO: 实现模式匹配清理
            return self.cache_manager.cleanup_expired()
        else:
            self.cache_manager.clear()
            return 0
    
    def get_service_stats(self) -> Dict[str, Any]:
        """
        获取服务统计信息
        
        Returns:
            服务统计数据
        """
        cache_stats = self.cache_manager.get_stats()
        api_stats = self.api_client.get_stats()
        
        return {
            'cache': cache_stats,
            'api': api_stats,
            'service_status': 'active'
        }


# 全局数据服务实例
_data_service: Optional[DataService] = None


def get_data_service() -> DataService:
    """
    获取全局数据服务实例
    
    Returns:
        数据服务实例
    """
    global _data_service
    
    if _data_service is None:
        _data_service = DataService()
    
    return _data_service


if __name__ == "__main__":
    # 测试代码
    def test_data_service():
        service = DataService()
        
        try:
            # 测试系统状态
            status = service.get_system_status()
            print(f"系统状态: {status}")
            
            # 测试实时行情
            quotes = service.get_realtime_quotes(['000001.SZ'])
            print(f"实时行情: {quotes}")
            
            # 测试持仓信息
            positions = service.get_portfolio_positions()
            print(f"持仓信息: {positions}")
            
            # 获取服务统计
            stats = service.get_service_stats()
            print(f"服务统计: {stats}")
            
        except Exception as e:
            print(f"测试失败: {str(e)}")
    
    # 运行测试
    test_data_service()